package com.imu.purse.modules.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.imu.common.utils.PhoneUtil;
import com.imu.constant.Constant;
import com.imu.core.base.BaseService;
import com.imu.purse.modules.app.dao.ImuUserIdentiryMapper;
import com.imu.purse.modules.app.dao.ImuUserInvMapper;
import com.imu.purse.modules.app.dao.ImuUserMapper;
import com.imu.purse.modules.app.entity.ImuUserEntity;
import com.imu.purse.modules.app.entity.ImuUserInvEntity;
import com.imu.purse.modules.app.form.RegisterForm;
import com.imu.purse.modules.app.service.ImuUserService;
import com.imu.purse.modules.bitcoin.YtfcoinApi;
import com.imu.purse.modules.trade.dao.FundMapper;
import com.imu.purse.modules.trade.dao.TradeInfoMapper;
import com.imu.purse.modules.trade.entity.FundEntity;
import com.imu.purse.modules.trade.entity.TradeInfoEntity;
import com.imu.utils.ShortUUID;
import com.qiniu.util.StringUtils;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;
import com.xiaoleilu.hutool.util.ArrayUtil;
import com.xiaoleilu.hutool.util.NumberUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 用户信息
 * @author sunhongwei
 * @email sunhongwei@jshijian.com
 * @date 2018-03-21 10:11:22
 * Copyright (c) 2017 武汉极时间科技有限公司 版权所有 
 * Jshijian aloha CO.,LTD. All Rights Reserved. 
 */
@Service
public class ImuUserServiceImpl extends BaseService<ImuUserEntity> implements ImuUserService 
{
	@Override
    @Transactional
    public int save(ImuUserEntity imuUser,String userInvPhone)
	{
		imuUser.setTimeCreate(new Date());
    	imuUser.setTimeUpdate(new Date());
    	super.insert(imuUser); 

    	redisTemplate.opsForValue().set(imuUser.getPhone(), JSON.toJSONString(imuUser));

    	if(!StringUtils.isNullOrEmpty(userInvPhone)){
			//插入之后再处理邀请人表
			ImuUserInvEntity iuin = new ImuUserInvEntity();
			iuin.setUserId(imuUser.getId());
			iuin.setTimeCreate(new Date());
			iuin.setUserUpdate(imuUser.getId());

			String userStr = redisTemplate.opsForValue().get(userInvPhone);
			if(!StringUtils.isNullOrEmpty(userStr)){
				ImuUserEntity tmpUser = JSON.parseObject(userStr,ImuUserEntity.class);
				iuin.setUserInvId(tmpUser.getId());
			}
			imuUserInvMapper.insert(iuin);
    	}
    	return 1;
	}
	
	@Override
	@Transactional
    public int updatePhone(final ImuUserEntity imuUser) 
    {
		//userName存了修改之前的手机号
		String oldPhone = imuUser.getUserName();
		//更新之后之前的缓存数据不变，将新的手机号数据获取之后保存到数据库   但是身份宝手机号要修改
    	imuUser.setTimeUpdate(new Date());
    	imuUser.setUserName(imuUser.getPhone());
    	int i = mapper.updateByPrimaryKeySelective(imuUser);
    	//将新数据保存到缓存
    	String str = JSON.toJSONString(imuUser); 
    	redisTemplate.opsForValue().set(imuUser.getPhone(), str);
    	//修改redis之前的手机号的身份宝数据
    	Object QrCode = redisTemplate.opsForHash().get("googleQrCode", oldPhone);
    	//将现在的手机号更新进redis并删除之前redis
    	if(null != QrCode){//有可能没有绑定过身份认证消息
    		redisTemplate.opsForHash().put("googleQrCode", imuUser.getPhone(),QrCode);
        	redisTemplate.opsForHash().delete("googleQrCode", oldPhone);
        	//修改数据库的值
        	imuUserIdentiryMapper.updByUserId(imuUser.getId());
    	}
    	
    	return i;
    }
    
    @Override
	@Transactional
    public int saveUpdate(final ImuUserEntity imuUser)
    {
    	int len = 0;
    	
    	if(1 > (len = this.update(imuUser)))
    	{
        	len = this.insert(imuUser);
    	}
    	
    	return len;
    }
    
 	@Override
	@Transactional
    public boolean delete(final String ...ids)
    {
    	if(ArrayUtil.isEmpty(ids)) return false;
    	
    	for (String id : ids) 
    	{
    		if(StrUtil.isBlank(id)) continue;
    		
    		if(NumberUtil.isNumber(id))
    		{
        		mapper.deleteByPrimaryKey(Long.valueOf(id));
    		}
		}
    	
    	return true;
    }
    
    @Override
    public ImuUserEntity findById(final Long id)
    {
    	if(null == id) return null;
    	return mapper.selectByPrimaryKey(id);
    }
    
    @Override
    public List<ImuUserEntity> queryList(final ImuUserEntity imuUser)
    {
    	if (imuUser.getPage() != null && imuUser.getLimit() != null)
    	{
            PageHelper.startPage(imuUser.getPage(), imuUser.getLimit());
        }
    	
    	return mapper.findByPage(imuUser);
    }
    
	@Override
	public ImuUserEntity queryByMobile(String phone) {
		ImuUserEntity userEntity = null;
		if(!PhoneUtil.isCPhone(phone)){ //非国内手机号码
			phone = phone.startsWith("00") ? phone : "00" + phone;
		}
		//先从缓存中获取，如果缓存中没有再从数据库获取
		String userStr = redisTemplate.opsForValue().get(phone);
		if(StrUtil.isEmpty(userStr) || "null".equals(userStr)){//null是如何进去
			userEntity = new ImuUserEntity();
			userEntity.setPhone(phone);
			userEntity = mapper.selectOne(userEntity);
			if(userEntity != null){
				redisTemplate.opsForValue().set(phone,JSON.toJSONString(userEntity));
			}
		}else{
			userEntity = JSON.parseObject(userStr,ImuUserEntity.class);
			if(StrUtil.isEmpty(userEntity.getInterPhone())){//后台添加这个时候缓存没有清除，后台需要增加删除缓存的策略
				userEntity = new ImuUserEntity();
				userEntity.setPhone(phone);
				userEntity = mapper.selectOne(userEntity);
				if(userEntity != null && StrUtil.isNotEmpty(userEntity.getInterPhone())){
					redisTemplate.opsForValue().set(phone,JSON.toJSONString(userEntity));
				}
			}
		}
		return userEntity;
	}
	
	@Override
	public ImuUserEntity login(final String phone,final String coreAddress)
	{
		FundEntity entity = null;
		ImuUserEntity imuUser = new ImuUserEntity();
		imuUser.setPhone(phone);
		imuUser = mapper.selectOne(imuUser);
		if(imuUser != null){
			String userStr = redisTemplate.opsForValue().get(phone);
			if(StrUtil.isEmpty(userStr)){
				redisTemplate.opsForValue().set(phone,JSON.toJSONString(imuUser));
			}
			entity = fundMapper.findByUserId(imuUser.getId());
			if(entity == null || null == entity.getUserId()){ //用户表存在数据，资金表不存在
				FundEntity fEntity = new FundEntity();
				fEntity.setUserId(imuUser.getId());
				fEntity.setTimeCreate(new Date());
				//初始化资金表其他字段
				initFund(fEntity);
				initMoneyAddress(phone,fEntity,coreAddress,imuUser.getId());
				fundMapper.insert(fEntity);
			}else{//存在资金信息
				if(StrUtil.isEmpty(entity.getMoneyAddress()) ||
						!entity.getMoneyAddress().startsWith(Constant.YTF_PREFIX)){//不是以太坊地址
					entity.setTimeUpdate(new Date());
					initMoneyAddress(phone,entity,coreAddress,imuUser.getId());
					fundMapper.upAddressById(entity);
				}else if(StrUtil.isNotEmpty(entity.getMoneyAddress())
						&& entity.getMoneyAddress().startsWith(Constant.YTF_PREFIX)){//将测试环境生成以太坊地址导入到生产上,缓存中不存在
					//删除之前换成
					if(!redisTemplate.opsForHash().hasKey(Constant.CORE_MONEY_USER_KEY,entity.getMoneyAddress())){//不存在，则插入
						redisTemplate.opsForHash().put(Constant.CORE_MONEY_USER_KEY,entity.getMoneyAddress(),
								imuUser.getId().toString());
					}
					if(!redisTemplate.opsForHash().hasKey(Constant.USER_CORE_MONEY_KEY,imuUser.getId().toString())){//不存在则插入
						//将用户ID和核心钱包ip绑定
						redisTemplate.opsForHash().put(Constant.USER_CORE_MONEY_KEY,imuUser.getId().toString(),coreAddress);
					}

				}
			}
		}

		return imuUser;
	}
	
	@Override
	@Transactional
	public int updates(ImuUserEntity entity) {
		// TODO Auto-generated method stub
		return mapper.updates(entity);
	}
	
	@Transactional
	public int registerUser(final RegisterForm form,final String moneyAddr,final String ytfPwd){
		/**
		 * 以下是保存用户的
		 */
		ImuUserEntity user = new ImuUserEntity();
        user.setPhone(form.getPhone());
        user.setUserName(form.getPhone());
        String salt = RandomStringUtils.randomAlphanumeric(20);
        user.setPwd(new Sha256Hash(form.getPwd(), salt).toHex());
        user.setPayPwd(new Sha256Hash(form.getPayPwd()).toHex());
        user.setSalt(salt);
        user.setTimeCreate(new Date());
        user.setState(1);//默認為啟用 該字段必須初始化
        save(user, form.getUserInvPhone());
        
        FundEntity fEntity = new FundEntity();
        fEntity.setUserId(user.getId());
        fEntity.setTimeCreate(user.getTimeCreate());
		fEntity.setMoneyAddress(form.getMoneyAddress());
		fEntity.setPassword(ytfPwd);
		//初始化资金表其他字段
		initFund(fEntity);
        fundMapper.insert(fEntity);
        if(StrUtil.isNotEmpty(ytfPwd)){
			//将钱包地址和用户id绑定 暂时屏蔽  2018-07-02 等对接好以太坊
			redisTemplate.opsForHash().put(Constant.CORE_MONEY_USER_KEY,fEntity.getMoneyAddress(),user.getId().toString());
			//将用户ID和核心钱包ip绑定
			redisTemplate.opsForHash().put(Constant.USER_CORE_MONEY_KEY,user.getId().toString(),moneyAddr);
		}
        return 1;
        
	}
	/**
	 * 忘记密码同时忘记密钥
	 */
	@Override
	@Transactional
	public int updates(ImuUserEntity imuUser, Long userId) {
		mapper.updateByPrimaryKeySelective(imuUser);
		imuUserIdentiryMapper.updByUserId(userId);
		redisTemplate.delete(imuUser.getPhone());
		return 1;
	}
	@Override
	@Transactional
    public int update(final ImuUserEntity imuUser) 
    {
    	int i = mapper.updateByPrimaryKeySelective(imuUser);
    	return i;
    }
	@Override
	public FundEntity showUserMoney(long uid) {
		
		return fundMapper.findByUserId(uid); 
	}
	/**
	 * 内部转账完成之后修改转出人与转账人信息   以及插入交易信息
	 */
	@Override
	@Transactional
	public int transaction(ImuUserEntity imuOutPerson, ImuUserEntity imuInPerson, String money, int status,
						   BigDecimal fee,String transId) {
		Date nowDate = new Date();
		BigDecimal big = new BigDecimal(money);

		if(status==0){//不同钱包内转账

			FundEntity fund = new FundEntity();
			fund.setUserId(imuOutPerson.getId());
			fund.setMoney(big);
			fund.setTimeUpdate(new Date());
			fundMapper.reduceMoney(fund);
			//接收人信息
			fund.setUserId(imuInPerson.getId());
			fundMapper.addMoney(fund);
		}else { //同一个钱包内部转账
			FundEntity fund = new FundEntity();
			fund.setUserId(imuOutPerson.getId());
			fund.setFrozenMoney(big.add(fee));
			fundMapper.moFrozenMoney(fund);
			
		}
		TradeInfoEntity tradeInfo = new TradeInfoEntity();
		tradeInfo.setPayUserId(imuOutPerson.getId());
		tradeInfo.setRecUserId(imuInPerson.getId());
		tradeInfo.setTransId(transId);
		tradeInfo.setOrderType(0);
		tradeInfo.setOrderState(0);
		if(status==0){
			tradeInfo.setOrderState(1);
		}
		tradeInfo.setMoney(big);
		tradeInfo.setOrderCreate(new Date());
		tradeInfo.setRecAddr(imuInPerson.getAddress());
		tradeInfo.setRecPhone(imuInPerson.getPhone());

		tradeInfo.setFee(fee);
		tradeInfo.setOrderNo(DateUtil.format(nowDate, "yyyyMMddHHmmssSSS"));

		tradeInfoMapper.insert(tradeInfo);
		tradeInfo = new TradeInfoEntity();
		tradeInfo.setPayUserId(imuInPerson.getId());
		tradeInfo.setRecUserId(imuOutPerson.getId());
		tradeInfo.setTransId(transId);
		tradeInfo.setOrderType(2);
		tradeInfo.setOrderState(0);

		if(status==0){
			tradeInfo.setOrderState(1);
		}
		tradeInfo.setMoney(big);
		tradeInfo.setOrderCreate(new Date());
		tradeInfo.setRecAddr(imuOutPerson.getAddress());
		tradeInfo.setRecPhone(imuOutPerson.getPhone());

		tradeInfo.setFee(fee);
		tradeInfo.setOrderNo(DateUtil.format(nowDate, "yyyyMMddHHmmssSSS"));

		tradeInfoMapper.insert(tradeInfo);
		return 1;
	}

	/**
	 * 初始化资金
	 * @param fEntity
	 */
	private void initFund(FundEntity fEntity){
		fEntity.setMoney(new BigDecimal(0));
		fEntity.setLockMoney(fEntity.getMoney());
		fEntity.setFrozenMoney(fEntity.getMoney());
		fEntity.setBj(fEntity.getMoney());
		fEntity.setBtc(fEntity.getMoney());
		fEntity.setFcg(fEntity.getMoney());
		fEntity.setHbc(fEntity.getMoney());
		fEntity.setHbb(fEntity.getMoney());
		fEntity.setIco(fEntity.getMoney());
		fEntity.setEth(fEntity.getMoney());
		fEntity.setFen(fEntity.getMoney());
		fEntity.setCowry(fEntity.getMoney());
		fEntity.setLockbj(fEntity.getMoney());
		fEntity.setLockfcg(fEntity.getMoney());
		fEntity.setLockico(fEntity.getMoney());
		fEntity.setLocketh(fEntity.getMoney());
		fEntity.setLockcowry(fEntity.getMoney());
	}

	/**
	 * 登录时创建用户钱包地址
	 * @param phone
	 * @param entity
	 * @param coreAddress
	 * @param userId
	 */
	private void initMoneyAddress(String phone,FundEntity entity,String coreAddress,Long userId){

		try {
			//删除之前的缓存
			if (StrUtil.isNotEmpty(entity.getMoneyAddress())) {
				redisTemplate.opsForHash().delete(Constant.CORE_MONEY_USER_KEY, entity.getMoneyAddress());
			}
			redisTemplate.opsForHash().delete(Constant.USER_CORE_MONEY_KEY, userId.toString());

			//随机选择核心钱包
			String ytfPwd = phone + ShortUUID.shortUUID();
			String newAddress = ytfcoinApi.createAccount(ytfPwd, coreAddress);
			if (StrUtil.isNotEmpty(newAddress)) {
				entity.setPassword(ytfPwd);
				entity.setMoneyAddress(newAddress);
				redisTemplate.opsForHash().put(Constant.CORE_MONEY_USER_KEY, newAddress, userId.toString());
				//将用户ID和核心钱包ip绑定
				redisTemplate.opsForHash().put(Constant.USER_CORE_MONEY_KEY, userId.toString(), coreAddress);
			}
		}catch(Exception e){
			log.error(e);
		}
	}
	@Autowired
	private ImuUserMapper mapper;
	
	@Autowired
	private ImuUserInvMapper imuUserInvMapper;
	
	@Autowired
	private FundMapper fundMapper;
	
	@Autowired
    private RedisTemplate<String, String> redisTemplate;
	
	@Autowired
	private ImuUserIdentiryMapper imuUserIdentiryMapper;
	
	@Autowired
	private TradeInfoMapper tradeInfoMapper;

	@Autowired
	private YtfcoinApi ytfcoinApi;

	private static final Log log = LogFactory.get(ImuUserService.class);
}
